/********************************************************************************************/
/* 	\file			dev_pm.c
 *	\date			
 *	\author			
 *	\model			
 *	\description	
 *	\version
 *
 *********************************************************************************************
 *	\par	Revision History:
 *	<!-----	No.		Date		Revised by		Details	------------------------------------->
 *
 ********************************************************************************************/

/********************************************************************************************/
/*							Include File Section											*/
/********************************************************************************************/
#include <string.h>
#include <stdbool.h>
#include "TypeDef.h"
#include "rtos.h"
#include "rtos_config.h"
#include "dev_pm.h"

#include "dspi0.h"
#include "dspi_driver.h"

#include "pins_driver.h"

#include "eMIOS_Mc2.h"
#include "eMIOS_Pwm2.h"
#include "emios_common.h"
#include "emios_ic_driver.h"
#include "emios_mc_driver.h"

/********************************************************************************************/
/*							Macro Definition Section										*/
/********************************************************************************************/
#define PMIC_REG_PWR_CONFIG             (0x31)

#define PMIC_WRITE_BIT_MASK		        (0x40)
#define PMIC_READ_BIT_MASK		        (0xBF)

#define PMIC_PARITY_BIT_ODD             (0u)
#define PMIC_PARITY_BIT_EVEN            (1u)
#define PMIC_PARITY_ZERO_MASK           (0x7F)
#define PMIC_PARITY_ONE_MASK            (0x80)
#define PMIC_CH_DEFAULT_VALUE           (0x20)

#define PMIC_CH_LDO_ENABLE_MASK         (0x10)
#define PMIC_CH_BUCK1_ENABLE_MASK       (0x80)
#define PMIC_CH_BUCK2_ENABLE_MASK       (0x40)
#define PMIC_CH_BUCK3_ENABLE_MASK       (0x20)
#define PMIC_CH_BOOST_ENABLE_MASK       (0x08)

#define PMIC_CH_LDO_DISABLE_MASK        (0xEF)
#define PMIC_CH_BUCK1_DISABLE_MASK      (0x7F)
#define PMIC_CH_BUCK2_DISABLE_MASK      (0xBF)
#define PMIC_CH_BUCK3_DISABLE_MASK      (0xDF)
#define PMIC_CH_BOOST_DISABLE_MASK      (0xF7)

/********************************************************************************************/
/*							Type Definition Section											*/
/********************************************************************************************/

/********************************************************************************************/
/*							Enumeration Type Definition Section								*/
/********************************************************************************************/

/********************************************************************************************/
/*							Structure/Union Type Definition Section							*/
/********************************************************************************************/

/********************************************************************************************/
/*							Global Variable Definition Section								*/
/********************************************************************************************/

/********************************************************************************************/
/*							Static Variable Definition Section								*/
/********************************************************************************************/

/********************************************************************************************/
/*							Static Prototype Declaration Section							*/
/********************************************************************************************/
static void i32PmDevice_Delay_200us(unsigned int cnt);
static void vdPmDevice_Pmic_Power_Config_Default(void);
static uint8 u8PmDevice_Pmic_CalcParityBit(uint8* u8Data_p,uint32 u32Length);
static int32 i32PmDevice_Pmic_Read(uint8 u8Addr,uint8* u8Data_p);
static int32 i32PmDevice_Pmic_Write(uint8 u8Addr,uint8* u8Data_p);

/********************************************************************************************/
/*							ROM Table Section												*/
/********************************************************************************************/
static const uint8 u8Pmic_Channel_EnabelBit_Mask_Tbl[DEV_PM_PMIC_CH_MAX]={
    PMIC_CH_LDO_ENABLE_MASK,
    PMIC_CH_BUCK1_ENABLE_MASK,
    PMIC_CH_BUCK2_ENABLE_MASK,
    PMIC_CH_BUCK3_ENABLE_MASK,
    PMIC_CH_BOOST_ENABLE_MASK,
};

static const uint8 u8Pmic_Channel_DisabelBit_Mask_Tbl[DEV_PM_PMIC_CH_MAX]={
    PMIC_CH_LDO_DISABLE_MASK,
    PMIC_CH_BUCK1_DISABLE_MASK,
    PMIC_CH_BUCK2_DISABLE_MASK,
    PMIC_CH_BUCK3_DISABLE_MASK,
    PMIC_CH_BOOST_DISABLE_MASK,
};

/********************************************************************************************/
/*							Function Definition Section										*/
/********************************************************************************************/
void vdPmDevice_Init(void){
    /*InitSPI*/
    DSPI_MasterInit(INST_DSPI0,&dspi0State,&dspi0_MasterInitConfig0);
    DSPI_MasterSetDelay(INST_DSPI0, 2, 2, 2);
    /* Pull PMIC wakeup line to high state */
    //PINS_DRV_WritePin((GPIO_Type *)(GPIO_BASE_PTRS[91 / 16]), (pins_channel_type_t)(91 % 16), (pins_level_type_t)1);
    PINS_DRV_WritePin(PTF, (pins_channel_type_t)(11), (pins_level_type_t)1);
    i32PmDevice_Delay_200us(75);
    /*KickDog(Init PWM to generate raising edge on every 50mSec time period)*/
    /* Disable eMIOS Global */
    //EMIOS_DRV_DisableGlobalEmios(INST_EMIOS_MC2);
	/*CLockBusBSet*/
    EMIOS_DRV_MC_InitCounterMode(INST_EMIOS_MC2, EMIOS_CNT_BUSB_DRIVEN, &eMIOS_Mc2_CntChnConfig0);
    /*PWM_Out*/
    EMIOS_DRV_PWM_InitMode(INST_EMIOS_MC2, EMIOS_PWM2_CHANNEL2,&eMIOS_Pwm2_PWMChnConfig0);
    /* Enable eMIOS Global */
    EMIOS_DRV_EnableGlobalEmios(INST_EMIOS_MC2);
    /*Turn All Power*/
    vdPmDevice_Pmic_Power_Config_Default();
}

int32 i32PmDevice_Pmic_Power_Config(DEV_PM_PMIC_Channel_t i32Ch,bool bEnable){
    int32 i32Rtn = RTOS_ERR_NONE;
    uint8 u8ConfigValue = PMIC_CH_DEFAULT_VALUE;
    uint32 u32ChannelIndex = NULL;
    
    i32PmDevice_Pmic_Read(PMIC_REG_PWR_CONFIG,&u8ConfigValue);
    u8ConfigValue |= PMIC_CH_DEFAULT_VALUE;
    
    for(u32ChannelIndex = 0;u32ChannelIndex < DEV_PM_PMIC_CH_MAX;u32ChannelIndex++){
        if(bEnable == TRUE){
            u8ConfigValue |= u8Pmic_Channel_EnabelBit_Mask_Tbl[u32ChannelIndex];
        }
        else{
            u8ConfigValue &= u8Pmic_Channel_DisabelBit_Mask_Tbl[u32ChannelIndex];
        }
    }

    i32PmDevice_Pmic_Write(PMIC_REG_PWR_CONFIG,&u8ConfigValue);
    return i32Rtn;
}

static void i32PmDevice_Delay_200us(unsigned int cnt){
    /* 200 us per cnt */
   unsigned int i[2];
   i[0] = cnt;
   while(i[0]--){
	   i[1] = 800;
	   while(i[1]--){
		   portNOP();
	   }
   }
   portNOP();
}

static void vdPmDevice_Pmic_Power_Config_Default(void){
    uint8 u8ConfigValue = 0x78; /*Enable All Power Channel*/
    i32PmDevice_Pmic_Write(PMIC_REG_PWR_CONFIG,&u8ConfigValue);
}

static uint8 u8PmDevice_Pmic_CalcParityBit(uint8* u8Data_p,uint32 u32Length){
	uint8 index;
    uint8 temp_val;
	uint8 parity;
    /* Identifying the parity as per the the PMIC data sheet */
	parity = 0x00;
	for (index = 0; index < u32Length; index++)
	{
		temp_val = u8Data_p[index];

		while (temp_val > 0)
		{
			parity = (parity + (temp_val & 0x01)) % 2;
			temp_val >>= 1;
		}
	}
    /* updating the parity bit as odd parity */
	if (0x00 != parity)
	{
		return PMIC_PARITY_BIT_ODD;
	}
	else
	{
		return PMIC_PARITY_BIT_EVEN;
	}

}
static int32 i32PmDevice_Pmic_Read(uint8 u8Addr,uint8* u8Data_p){
    int32 i32Rtn = RTOS_ERR_NONE;
    status_t status = STATUS_SUCCESS;
    uint8 u8SpiDataTx[2] = {0,0};
    uint8 u8SpiDataRx[2] = {0,0};
    u8SpiDataTx[0] = u8Addr & PMIC_READ_BIT_MASK;
    u8SpiDataTx[1] = *u8Data_p;
    if(u8PmDevice_Pmic_CalcParityBit(u8SpiDataTx,sizeof(u8SpiDataTx))){
        u8SpiDataTx[0] &= PMIC_PARITY_ZERO_MASK;
    }
    else{
        u8SpiDataTx[0] |= PMIC_PARITY_ONE_MASK;
    }
    
	/* Start the transfer */
	status = DSPI_MasterTransfer(INST_DSPI0,u8SpiDataTx,u8SpiDataRx,sizeof(u8SpiDataTx));
    {
        dspi_transfer_status_t transfer_status = DSPI_TRANSFER_FAIL;
        while (DSPI_IN_PROGRESS == transfer_status){
            (void)DSPI_GetTransferStatus(INST_DSPI0, &transfer_status);
        }
        *u8Data_p = u8SpiDataRx[1];
    }
	if (status != STATUS_SUCCESS)
	{
	    i32Rtn = RTOS_ERR_NG;
		//printf("dspi master transfer fail,status=%lu\r\n", (uint16_t)status);
	}
    return i32Rtn;
}

static int32 i32PmDevice_Pmic_Write(uint8 u8Addr,uint8* u8Data_p){
    int32 i32Rtn = RTOS_ERR_NONE;
    status_t status = STATUS_SUCCESS;
    uint8 u8SpiDataTx[2] = {0,0};
    uint8 u8SpiDataRx[2] = {0,0};
    u8SpiDataTx[0] = u8Addr | PMIC_WRITE_BIT_MASK;
    u8SpiDataTx[1] = *u8Data_p;
    if(!u8PmDevice_Pmic_CalcParityBit(u8SpiDataTx,sizeof(u8SpiDataTx))){
        u8SpiDataTx[0] &= PMIC_PARITY_ZERO_MASK;
    }
    else{
        u8SpiDataTx[0] |= PMIC_PARITY_ONE_MASK;
    }
    
	/* Start the transfer */
	status = DSPI_MasterTransfer(INST_DSPI0,u8SpiDataTx,u8SpiDataRx,sizeof(u8SpiDataTx));
    {
        dspi_transfer_status_t transfer_status = DSPI_TRANSFER_FAIL;
        while (DSPI_IN_PROGRESS == transfer_status){
            (void)DSPI_GetTransferStatus(INST_DSPI0, &transfer_status);
        }
    }
	if (status != STATUS_SUCCESS)
	{
	    i32Rtn = RTOS_ERR_NG;
		//printf("dspi master transfer fail,status=%lu\r\n", (uint16_t)status);
	}
    return i32Rtn;
}

/* End of File */
